package com.vrv.common.utils;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;

/**
 *
 * IP地址工具类
 *
 * @author 曹保利
 *
 */
public class IpUtil {

    /**
     * 从request中获取IP地址
     *
     * @param request
     * @return
     */
    public static String getRemoteIP(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.split(",").length > 0) {
            ip = ip.split(",")[0];
        }
        return ip;
    }

    // 计算出掩码指定的IP地址个数 如: 24
    public static long ipCount(int mask) {
        long number = 0;
        for (int i = 0; i < 32 - mask; i++) {
            number += Math.pow(2, i);
        }
        return number;
    }

    // 分割IP地址
    public static long[] splitIp(String ip) {
        long[] ipArray = new long[4];
        int position1 = ip.indexOf(".");
        int length = ip.length();
        if (length >= 7 && length < 16) {
            if (position1 > 0) {
                int position2 = ip.indexOf(".", position1 + 1);
                if (position2 > 0) {
                    int position3 = ip.indexOf(".", position2 + 1);
                    if (position3 > 0 && position3 < length - 1) {
                        try {
                            ipArray[0] = Long.parseLong(ip.substring(0, position1));
                            ipArray[1] = Long.parseLong(ip.substring(position1 + 1, position2));
                            ipArray[2] = Long.parseLong(ip.substring(position2 + 1, position3));
                            ipArray[3] = Long.parseLong(ip.substring(position3 + 1));
                        } catch (NumberFormatException e) {
                            return null;
                        }
                    } else {
                        return null;
                    }
                } else {
                    return null;
                }
            } else {
                return null;
            }
        } else {
            return null;
        }
        return ipArray;
    }

    /**
     * 将10.0.0.0形式的ip地址转换成10进制整数
     *
     * @param str
     * @return
     */
    public static long ipToLong(String str) {
        long[] ip = splitIp(str);
        if (ip != null) {
            // ip0*256*256*256+ip1*256*256+ip2*256+ip3
            return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
        } else {
            return 0;
        }
    }

    // 将10.0.0.0形式的掩码地址转换成10进制整数
    public static long maskToLong(int mask) {
        long longMask = 0;
        for (int i = 31; i >= 32 - mask; i--) {
            longMask += Math.pow(2, i);
        }
        return longMask;
    }

    // 将10进制整数形式转换成127.0.0.1形式的IP地址
    public static String longToIP(long longIp) {
        StringBuffer sb = new StringBuffer("");
        sb.append(String.valueOf(longIp >>> 24));// 右移24位
        sb.append(".");
        sb.append(String.valueOf((longIp & 0x00FFFFFF) >>> 16)); // 将高8位置0，然后右移16位
        sb.append(".");
        sb.append(String.valueOf((longIp & 0x0000FFFF) >>> 8));
        sb.append(".");
        sb.append(String.valueOf(longIp & 0x000000FF));
        return sb.toString();
    }

    /**
     * <p>
     * 判断 IP 是否存在于指定规则中<BR>
     * 思路如下：
     *
     * <pre>
     * 1.转换 【*-】 为 【0-】；
     * 2.转换 【-*】 为 【-255】;
     * 3.转换 【*】  为 【0-255】;
     * 4.去除 【[]】 为 【】
     * 5.提取最大、最小两个IP值;
     * 6、把 IP 转化为 Long，通过比较大小判断是否在指定规则中。
     * </pre>
     *
     * <pre>
     * 用法如下：
     * <OL>
     * <LI>*.*.*.*                          代表 0.0.0.0 至 255.255.255.255
     * <LI>192.168.0.*                      代表 192.168.0.0 至 192.168.0.255
     * <LI>192.168.0.[0-255]                代表 192.168.0.0 至 192.168.0.255
     * <LI>192.168.*.[0-255]                代表 192.168.0.0 至 192.168.255.255
     * <LI>[0-*].[*-20].*.[0-255]           代表 0.0.0.0 至 255.20.255.255
     * <LI>[0-255].[0-255].[0-255].[0-255]  代表 0.0.0.0 至 255.255.255.255
     * </pre>
     *
     * @param pattern
     *            IP规则
     * @param ip
     *            判定IP
     * @return
     */
    public static boolean compare(String pattern, String ip) {
        if (StringUtils.isBlank(pattern) || StringUtils.isBlank(ip)) {
            return false;
        }
        pattern = pattern.replaceAll("[^\\.]*-", "0-").replaceAll("-[^\\.]*", "-255").replaceAll("[^\\.]*\\*[^\\.]*", "0-255").replace("[", "").replace("]", "");

        String minIp = pattern.replaceAll("-[^\\.]*", "");
        String maxIp = pattern.replaceAll("[^\\.]*-", "");

        Long ipValue = Long.valueOf(ipPad(ip).replace(".", ""));
        Long minValue = Long.valueOf(ipPad(minIp).replace(".", ""));
        Long maxValue = Long.valueOf(ipPad(maxIp).replace(".", ""));

        if (ipValue >= minValue && ipValue <= maxValue) {
            return true;
        }

        return false;
    }

    /**
     * 补全 IP 地址<BR>
     * 把 IP: 1.1.1.1 补全为 IP: 001.001.001.001<BR>
     * 通过正则替换完成, 思路如下：
     *
     * <pre>
     * 1.IP 第   一  段,长度为 1、2 位补码；
     * 2.IP 第 二、三 段,长度为 1、2 位补码；
     * 3.IP 第   四  段,长度为 1、2 位补码；
     * </pre>
     *
     * @param ip
     *            IP地址
     * @return
     */
    public static String ipPad(String ip) {
        if (StringUtils.isBlank(ip)) {
            return ip;
        }
        ip = ip.replaceAll("^(\\d)[.]", "00$1.").replaceAll("^(\\d\\d)[.]", "0$1.");
        ip = ip.replaceAll("[.](\\d)[.]", ".00$1.").replaceAll("[.](\\d\\d)[.]", ".0$1.");
        ip = ip.replaceAll("[.](\\d)$", ".00$1").replaceAll("[.](\\d\\d)$", ".0$1");
        return ip;
    }

    public static void main(String[] args) {
        String ip = longToIP(3232235692L);
        System.err.println(ip);
    }

}
